package org.opengauss.evaluate.utils;

import com.github.javaparser.resolution.MethodUsage;
import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration;
import com.github.javaparser.resolution.types.ResolvedReferenceType;
import com.github.javaparser.resolution.types.ResolvedType;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author biao.yang
 * @Description:
 * @date 2025/3/26 15:41
 */
public class SqlReplaceUtils {

    private static final Logger LOGGER = LoggerFactory.getLogger(SqlReplaceUtils.class);

    public static String analyzeDynamicParams(String sql, Map<String, ResolvedType> parameterTypes) {
        // 替换 <script>
        sql = sql.replace("<script>", "");
        sql = sql.replace("</script>", "");

        // 替换 &gt; &lt;
        sql = sql.replace("&gt;", ">");
        sql = sql.replace("&lt;", "<");

        if(sql.contains("select PROVINCE,PRODUCE_MONTH, sum(TOTAL_CAPACITY) as TOTAL_CAPACITY")){
            System.out.println(1);
        }
        // 替换<foreach>
        sql = replaceForeach(sql);

        // 替换<where>
        sql = replaceWhere(sql);

        // 替换<if></if>
        sql = replaceIf(sql);

        // 替换${}
        sql = dollarPlaceHolder(sql);
        // 替换#{}
        sql = simplePlaceHolder(sql, parameterTypes);

        // 替换一些特殊字符
        sql = replaceSpecial(sql);

        LOGGER.info("Replace SQL: {}", sql);

        return sql;
    }

    private static String simplePlaceHolder(String sql, Map<String, ResolvedType> parameterTypes){
        Pattern pattern = Pattern.compile("[#]\\{([^}]+)\\}");
        Matcher matcher = pattern.matcher(sql);
        while (matcher.find()) {
            String paramExpr = matcher.group(1);
            LOGGER.info("place holder is {}", paramExpr);

            String[] parts = paramExpr.split("\\.");
            if (parts.length == 0) continue;

            String objectName = parts[0];
            ResolvedType currentType = parameterTypes.get(objectName);
            if (currentType == null) {
                LOGGER.info("Parameter '{}' not found.", objectName);
                continue;
            }

            StringBuilder typePath = new StringBuilder();
            typePath.append(objectName).append(": ").append(currentType.describe());

            for (int i = 1; i < parts.length; i++) {
                String fieldName = parts[i];
                if (currentType instanceof ResolvedReferenceType) {
                    ResolvedReferenceType refType = (ResolvedReferenceType) currentType;
                    ResolvedType fieldType = findFieldOrGetterType(refType, fieldName);
                    if (fieldType == null) {
                        typePath.append(" -> ").append(fieldName).append(": Unknown");
                        break;
                    }
                    typePath.append(" -> ").append(fieldName).append(": ").append(fieldType.describe());
                    currentType = fieldType;
                } else {
                    break;
                }
            }
            LOGGER.info("Dynamic param {} types: {}", paramExpr, typePath);

            sql = replaceFieldValue(sql, matcher.group(0), currentType);
        }
        return sql;
    }

    private static String replaceFieldValue(String sql, String paramExpr ,ResolvedType currentType){
        String replacement = generateValueByType(currentType);
        sql = sql.replace(paramExpr, replacement);

        return sql;
    }





    private static ResolvedType findFieldOrGetterType(ResolvedReferenceType refType, String fieldName) {
        // 查找字段
        for (ResolvedFieldDeclaration field : refType.getDeclaredFields()) {
            if (field.getName().equals(fieldName)) {
                return field.getType();
            }
        }
        // 查找getter方法
        String getterName = "get" + capitalize(fieldName);
        for (MethodUsage declaredMethod : refType.getDeclaredMethods()) {
            if (declaredMethod.getName().equals(getterName) && declaredMethod.getNoParams() == 0) {
                return declaredMethod.returnType();
            }
        }
        return null;
    }

    private static String capitalize(String s) {
        if (s == null || s.isEmpty()) return s;
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }



    /**
     * 根据类型生成示例值
     */
    private static String generateValueByType(ResolvedType type) {
        if (type.isPrimitive() || type.isReferenceType()) {
            String typeName = type.describe();
            switch (typeName) {
                case "java.lang.String":
                    return "str";
                case "java.lang.Integer":
                case "java.lang.Long":
                case "java.lang.Double":
                case "java.lang.Float":
                    return "1";
                case "java.lang.Boolean":
                    return "true";
                case "date":
                    return "'2023-10-01'";
                default:
                    if (type.isReferenceType() && type.asReferenceType().getTypeDeclaration().isPresent()) {
                        String className = type.asReferenceType().getTypeDeclaration().get().getName();
                        if (className.equals("LocalDateTime")) {
                            return "'2023-10-01 12:00:00'";
                        }
                    }
                    return "null"; // 其他复杂类型返回null
            }
        }
        return "null";
    }


    private static String replaceIf(String sql){
        String pattern = "<if.*?>(.*?)</if>";
        Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
        Matcher m = r.matcher(sql);
        StringBuilder result = new StringBuilder();
        int lastEnd = 0;

        // 查找匹配项并提取中间内容
        while (m.find()) {
            result.append(sql, lastEnd, m.start());
            result.append(m.group(1).trim());
            lastEnd = m.end();
        }
        result.append(sql.substring(lastEnd));
        return result.toString();
    }


    private static String replaceForeach(String sql){
        String pattern = "<foreach.*?>(.*?)</foreach>";
        Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
        Matcher m = r.matcher(sql);
        StringBuilder result = new StringBuilder();
        int lastEnd = 0;

        // 查找匹配项并提取中间内容
        while (m.find()) {
            final String startTag = m.group(0);
            // 提取 collection 和 item 属性值
            String collection = extractAttribute(startTag, "collection");
            String item = extractAttribute(startTag, "item");
            String open = extractAttribute(startTag, "open");
            String close = extractAttribute(startTag, "close");

            String context = m.group(1).trim();
            assert item != null;
            context = context.replace(item, collection + "-generic");

            result.append(sql, lastEnd, m.start());
            if(StringUtils.isNotBlank(open)){
                result.append(open);
            }
            result.append(context);
            if(StringUtils.isNotBlank(close)){
                result.append(close);
            }
            lastEnd = m.end();
        }
        result.append(sql.substring(lastEnd));
        return result.toString();
    }

    private static String replaceWhere(String sql){
        String pattern = "<where>(.*?)</where>";
        Pattern r = Pattern.compile(pattern, Pattern.DOTALL);
        Matcher m = r.matcher(sql);
        StringBuilder result = new StringBuilder();
        int lastEnd = 0;

        // 查找匹配项并提取中间内容
        while (m.find()) {
            result.append(sql, lastEnd, m.start());
            result.append(m.group(1).trim());
            result.append(" where 1=1 ");
            lastEnd = m.end();
        }
        result.append(sql.substring(lastEnd));
        return result.toString();
    }

    private static String dollarPlaceHolder(String sql){
        if(sql.contains("SELECT hours.province, hours.${areaType}")){
            System.out.println(1);
        }
        // 正则匹配六种情况（优先级由高到低）：
        // 1. ${var} AS （后跟 AS 和空格）
        // 2. ( ${var} ) （括号包裹，允许空格）
        // 3. ${var}.    （后跟点号）
        // 4. .${var}   （前导点号）
        // 5. =${var}   （前导等号，允许空格）
        // 6. ${var}    （独立存在）
        String regex = "(\\$\\{.*?}\\s+(?i)AS\\b)" +   // Case 1: ${var} AS
                "|(\\(\\s*\\$\\{.*?}\\s*\\))" + // Case 2: ( ${var} )
                "|(\\$\\{.*?}\\.)" +        // Case 3: ${var}.
                "|(\\.\\$\\{.*?})" +         // Case 4: .${var}
                "|(=\\s*\\$\\{.*?})" +       // Case 5: = ${var}
                "|(\\$\\{.*?})";             // Case 6: ${var}

        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
        Matcher matcher = pattern.matcher(sql);

        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            String replacement = "";
            if (matcher.group(1) != null) {         // Case 1: ${var} AS
                replacement = "field AS";       // 保留 AS（如 ${var} AS → schema AS）
            } else if (matcher.group(2) != null) {  // Case 2: ( ${var} )
                replacement = "(field)"; // 保留括号和空格（如 (${var}) → (schema)）
            } else if (matcher.group(3) != null) {  // Case 3: ${var}.
                replacement =  "schema.";
            } else if (matcher.group(4) != null) {  // Case 4: .${var}
                replacement = ".field";
            } else if (matcher.group(5) != null) {  // Case 5: = ${var}
                replacement = "= ''";
            } else if (matcher.group(6) != null) {  // Case 6: ${var}
                replacement = "";
            }
            matcher.appendReplacement(sb, replacement);
        }
        matcher.appendTail(sb);
        return sb.toString();
    }


    private static String replaceSpecial(String sql){
        // 替换 \"或\\"
        String pattern = "(\"|\\\\+\")";
        String output = sql.replaceAll(pattern, "");

        // 替换 \n或\\n
        pattern = "(\\n|\\\\n)";
        output = output.replaceAll(pattern, "");

        return output;
    }


    // 从标签中提取属性值（支持单/双引号）
    private static String extractAttribute(String tag, String attrName) {
        Pattern pattern = Pattern.compile(
                attrName + "\\s*=\\s*(\\\\?[\"'])(.*?)\\\\?\\1",
                Pattern.CASE_INSENSITIVE
        );
        Matcher matcher = pattern.matcher(tag);
        return matcher.find() ? matcher.group(2) : null;
    }
}
